#include <user.h>
#include <bwio.h>
#include <ts7200.h>
#include <curses.h>
#include <defs.h>

#define TIMER4_LVAL 0x80810060
#define TIMER4_HVAL 0x80810064
#define T4EN_MASK   0x100
#define TIMER4_TICKS_PER_SECOND 983000

#define M 10000
#define N 1000

int timer4_init() {
  int *timer4_hval = (int*)( TIMER4_HVAL );
  *timer4_hval = T4EN_MASK;
}

int timer4_read() {
  int *timer4_lval = (int*)( TIMER4_LVAL );
  return *timer4_lval;
}

void UserInit() {
  int i;
  
  // init stats
  int start, end;
  double x;
  double n = 0.0;
  double mean = 0.0;
  double M2 = 0.0;
  double min = 1.0, max = 0.0;

  // init send buffer
  char buf[M+1];
  for (i = 0; i < M; i++) {
    buf[i] = '.';
  }
  buf[M] = '\0';

  // init timer
  timer4_init();

  // time terminal send
  start = timer4_read();
  bwputstr(COM2, buf);
  end = timer4_read();
  x = (double)(end - start)/TIMER4_TICKS_PER_SECOND;
  int irate = (x*1000000)/M;
  bwprintf(COM2, "\x1b[2J");

  // time context switch
  for (i = 0; i < N; i++) {
    start = timer4_read();
    Pass();
    end = timer4_read();

    // use Knuth's variance algorithm to update mean, variance
    x = (double)(end - start)/TIMER4_TICKS_PER_SECOND;
    if (x < min) min = x;
    if (x > max) max = x;
    n += 1.0;
    double delta = x-mean;
    mean += delta/n;
    M2 += delta*(x-mean);
  }
  double var = M2/(N-1);
  int imin = min*1000000;
  int imax = max*1000000;
  int iavg = mean*1000000;
  int ivar = var*1000000;
  
  bwprintf(COM2, "PerfTest v 0.1\r\n");
  bwprintf(COM2, "terminal rate is %d us\r\n", irate);
  bwprintf(COM2, "performed %d context switches\r\n", N);
  bwprintf(COM2, "min\t%d us\r\n", imin);
  bwprintf(COM2, "max\t%d us\r\n", imax);
  bwprintf(COM2, "avg\t%d us\r\n", iavg);
  bwprintf(COM2, "var\t%d us\r\n", ivar);

  Exit();
}
